package com.promise.jokerdream.work.knight.island

import com.promise.jokerdream.database.entity.KnightMissionGameConfigEntity
import com.promise.jokerdream.manager.ExecutionHistoryManager
import com.promise.jokerdream.repository.GameApi
import com.promise.jokerdream.repository.foldWithApiException
import com.promise.jokerdream.utils.AppContext
import com.promise.jokerdream.work.BaseWork
import com.promise.jokerdream.work.WorkResult

// 侠客岛工作
class KnightIslandWork(
    private val config: KnightMissionGameConfigEntity,
    uin: String
): BaseWork(uin) {

    override val name: String
        get() = "侠客岛"

    private val gameApi = GameApi.getInstance()
    private val historyManager by lazy { ExecutionHistoryManager.getInstance(AppContext.get()) }

    override suspend fun executeWork(): WorkResult {
        try {
            val selectedKnightRewardsList = if (config.selectedKnightRewards.isEmpty()) emptyList() else config.selectedKnightRewards.split(",").map { it.trim() }
            if (selectedKnightRewardsList.isEmpty()) {
                return WorkResult.Success
            }
            
            return processMissions(selectedKnightRewardsList)
        } catch (e: Exception) {
            historyManager.addHistory(name, e.message)
            return WorkResult.Failure(e, e.message)
        }
    }
    
    private suspend fun processMissions(selectedKnightRewards: List<String>): WorkResult {
        val queryResult = gameApi.queryKnightIslandMission()
        return queryResult.foldWithApiException(
            onSuccess = { response ->
                var currentResponse = response
                var hasChanges = true
                
                while (hasChanges) {
                    hasChanges = false
                    for (mission in currentResponse.mission) {
                        when (mission.status) {
                            0 -> {
                                if (isRewardMatched(mission.reward, selectedKnightRewards)) {
                                    val autoAssignResult = gameApi.autoAssignKnightMission(mission.pos)
                                    autoAssignResult.foldWithApiException(
                                        onSuccess = { assignResponse ->
                                            val beginResult = gameApi.beginKnightMission(mission.pos)
                                            beginResult.foldWithApiException(
                                                onSuccess = { beginResponse ->
                                                    currentResponse = beginResponse
                                                    historyManager.addHistory(name, beginResponse.getDescription())
                                                },
                                                onFailure = { code, msg ->
                                                    historyManager.addHistory(name, msg, code)
                                                }
                                            )
                                        },
                                        onFailure = { code, msg ->
                                            historyManager.addHistory(name, msg, code)
                                        }
                                    )
                                } else if (currentResponse.fresh > 0) {
                                    val refreshResult = gameApi.refreshKnightMission(mission.pos)
                                    refreshResult.foldWithApiException(
                                        onSuccess = { refreshResponse ->
                                            currentResponse = refreshResponse
                                            historyManager.addHistory(name, refreshResponse.getDescription())
                                            hasChanges = true
                                        },
                                        onFailure = { code, msg ->
                                            historyManager.addHistory(name, msg, code)
                                        }
                                    )
                                }
                            }
                            2 -> {
                                // 领取奖励
                            }
                            else -> {
                                // nothing
                            }
                        }
                    }
                }
                WorkResult.Success
            },
            onFailure = { code, msg ->
                historyManager.addHistory(name, msg, code)
                WorkResult.Failure(Exception(msg), msg)
            }
        )
    }
    
    private fun isRewardMatched(reward: String, selectedKnightRewards: List<String>): Boolean {
        return selectedKnightRewards.any { selectedReward ->
            reward.contains(selectedReward)
        }
    }
}